package replicant2;

import Common.MyDatagramSocket;
import Common.RequestMessage;
import Common.Share;
import replicant2.GameServerInterfaceHelper;

import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.ReceiverAdapter;
import org.jgroups.View;
import org.jgroups.util.Util;
import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
import org.omg.PortableServer.POAPackage.ObjectNotActive;
import org.omg.PortableServer.POAPackage.ServantAlreadyActive;
import org.omg.PortableServer.POAPackage.WrongPolicy;

import replicant2.GameServerImpl;
import replicant2.GameServerInterface;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;

public class Replicant2 extends ReceiverAdapter {

	public final static String MULTICAST_SEND = "1";
	public final static String MULTICAST_RECV = "2";

	public static final Map<String, String> NameIpTable = new HashMap<String, String>() {
		{
			put("132", "NA");
			put("93", "EU");
			put("182", "AS");
		}
	};

	private Map<String, GameServerInterface> _ipClient = new HashMap<String, GameServerInterface>();
	JChannel _channel = null;
	String _userName = System.getProperty("user.name", "n/a");

	public Replicant2() {

	}

	public void start(final String[] args) {
		
		try {
			
			
			new Thread(new Runnable() {
		           public void run() {
		        	   try {
						startCorba(args);
					} catch (InvalidName | ServantAlreadyActive
							| WrongPolicy | ObjectNotActive
							| FileNotFoundException | AdapterInactive e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}			
			}
		}).start();
			
			_channel = new JChannel();
			_channel.setReceiver(this);
			_channel.connect("ServerCluster");

			_ipClient.put("132", getServer(args, "132"));
			_ipClient.put("93", getServer(args, "93"));
			_ipClient.put("182", getServer(args, "182"));
			eventLoop();
			
			

		} catch (Exception e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
		}

		if (_channel != null) {
			_channel.close();
		}
	}

	public void receive(Message msg) {
		// String line=msg.getSrc() + ":receiver: " + msg.getObject();
		String line = msg.getObject().toString();
		System.out.println("receive multi-cast message:"+line);
		List<String> resu = Arrays.asList(line.split(Share.DELIMETER));
		if (resu.get(0).equals(MULTICAST_SEND)) {
			List<String> resu1 = resu.subList(1, resu.size()-1);
			String result = getResult(resu1);
			String multiMessage = MULTICAST_RECV + Share.DELIMETER
					+ "replicant2"+ Share.DELIMETER + result + Share.DELIMETER;
			Message resultmsg = new Message(null, null, multiMessage);
			try {
				_channel.send(resultmsg);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

	public void eventLoop() {

		while (true) {
		}
	}

	private String getPrefixIp(final String ip) {
		int index = ip.indexOf(".");
		return ip.substring(0, index);
	}

	private String getResult(List<String> paras) {
		if (paras.get(0).equals(RequestMessage.CREATE)) {
			if (paras.size() >= 7) {
				String ip = getPrefixIp(paras.get(6));
				if (_ipClient.containsKey(ip)) {
					GameServerInterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.createPlayerAccount(paras.get(1), paras.get(2), Integer.parseInt(paras.get(3)), paras.get(4), paras.get(5), paras.get(6));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.SIGNIN)) {
			if (paras.size() >= 4) {
				String ip = getPrefixIp(paras.get(3));
				if (_ipClient.containsKey(ip)) {
					GameServerInterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.playerSignIn(paras.get(1), paras.get(2), paras.get(3));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.SIGNOUT)) {
			if (paras.size() >= 3) {
				String ip = getPrefixIp(paras.get(2));
				if (_ipClient.containsKey(ip)) {
					GameServerInterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.playerSignOut(paras.get(1), paras.get(2));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.STATUS)) {
			if (paras.size() >= 4) {
				String ip = getPrefixIp(paras.get(3));
				if (_ipClient.containsKey(ip)) {
					GameServerInterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.getPlayerStatus(paras.get(1), paras.get(2), paras.get(3));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.SUSPEND)) {
			if (paras.size() >= 5) {
				String ip = getPrefixIp(paras.get(3));
				if (_ipClient.containsKey(ip)) {
					GameServerInterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.suspendAccount(paras.get(1), paras.get(2), paras.get(3),paras.get(4));
					}
				}
			}
		} else if (paras.get(0).equals(RequestMessage.TRANSFER)) {
			if (paras.size() >= 5) {
				String ip = getPrefixIp(paras.get(3));
				if (_ipClient.containsKey(ip)) {
					GameServerInterface gs = _ipClient.get(ip);
					if(gs!= null){
						return gs.transferAccount(paras.get(1), paras.get(2), paras.get(3),paras.get(4));
					}
				}
			}
		}

		return "0";
	}

	private GameServerInterface getServer(String[] args, String ip) {
		GameServerInterface ret = null;
		try {
			ORB orb = ORB.init(args, null);
			String fileName = NameIpTable.get(ip) + "ior.txt";
			BufferedReader br;
			br = new BufferedReader(new FileReader(fileName));
			String ior = br.readLine();
			br.close();
			org.omg.CORBA.Object o = orb.string_to_object(ior);
			ret = GameServerInterfaceHelper.narrow(o);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return ret;
	}

	private void startCorba(String[] args) throws InvalidName,
			ServantAlreadyActive, WrongPolicy, ObjectNotActive,
			FileNotFoundException, AdapterInactive {
		ORB orb = ORB.init(args, null);
		POA rootPOA = POAHelper.narrow(orb
				.resolve_initial_references("RootPOA"));

		GameServerImpl ASServer = new GameServerImpl("AS");
		ASServer.startUdpServer();
		byte[] ASid = rootPOA.activate_object(ASServer);
		org.omg.CORBA.Object ASref = rootPOA.id_to_reference(ASid);
		String ASior = orb.object_to_string(ASref);
		PrintWriter ASfile = new PrintWriter("ASior.txt");
		System.out.println(ASior);
		ASfile.println(ASior);
		ASfile.close();

		GameServerImpl EUServer = new GameServerImpl("EU");
		EUServer.startUdpServer();
		byte[] EUid = rootPOA.activate_object(EUServer);
		org.omg.CORBA.Object EUref = rootPOA.id_to_reference(EUid);
		String EUior = orb.object_to_string(EUref);
		PrintWriter EUfile = new PrintWriter("EUior.txt");
		System.out.println(EUior);
		EUfile.println(EUior);
		EUfile.close();

		GameServerImpl NAServer = new GameServerImpl("NA");
		NAServer.startUdpServer();
		byte[] NAid = rootPOA.activate_object(NAServer);
		org.omg.CORBA.Object NAref = rootPOA.id_to_reference(NAid);
		String NAior = orb.object_to_string(NAref);
		PrintWriter NAfile = new PrintWriter("NAior.txt");
		System.out.println(NAior);
		NAfile.println(NAior);
		NAfile.close();

		rootPOA.the_POAManager().activate();
		orb.run();

	}

	public static void main(String[] args) throws Exception {

		new Replicant2().start(args);
		// System.out.println("this is a main java");
	}

}
